﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Excel = Microsoft.Office.Interop.Excel;
using PlanProd.Contracts;
using System.Data.OleDb;
using System.Data;
using System.Collections.Specialized;

namespace WebAppPlanProduccion.Code
{
    public class ExcelHelper
    {
        /// <summary>
        /// Recibe el pedido comercial detalle
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static List<PedidoComercialDetalle> GetPedidoComercialDetalleFromExcel(string filePath, PedidoComercial pedidoComercial, List<string> parseErrors)
        {
            List<PedidoComercialDetalle> pedidoComercialDetalleList = new List<PedidoComercialDetalle>();

            DataTable dataTable = GetDataTableFromExcel(filePath);
            int temporadaIndex = 0;
            int destinoIndex = 0;
            int productoIndex = 0;
            int colorIndex = 0;
            int cantidadIndex = 0;
            const int cantidadColumnas = 5;
            if (dataTable.Columns.Count != cantidadColumnas)
            {
                throw new Exception(string.Format("El excel debe contener {0} columnas", cantidadColumnas));
            }

            string value = string.Empty;
            for (int i = 0; i < cantidadColumnas; i++)
            {
                value = dataTable.Columns[i].ColumnName;
                if (value.ToLower() == "temporada")
                {
                    temporadaIndex = i;
                }
                else if (value.ToLower() == "destino")
                {
                    destinoIndex = i;
                }
                else if (value.ToLower() == "producto")
                {
                    productoIndex = i;
                }
                else if (value.ToLower() == "color")
                {
                    colorIndex = i;
                }
                else if (value.ToLower() == "cantidad")
                {
                    cantidadIndex = i;
                }
            }

            string temporada;
            string destino;
            string producto;
            string color;
            int cantidad;
            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                PedidoComercialDetalle pedidoComercialDetalle = new PedidoComercialDetalle();

                temporada = dataTable.Rows[i][temporadaIndex].ToString();
                destino = dataTable.Rows[i][destinoIndex].ToString();
                producto = dataTable.Rows[i][productoIndex].ToString();
                color = dataTable.Rows[i][colorIndex].ToString();

                bool errorEnTemporada = true;
                if (!String.IsNullOrEmpty(temporada))
                {
                    int temporadaInt;
                    if (int.TryParse(temporada, out temporadaInt))
                    {
                        if (temporadaInt == pedidoComercial.TemporadaId)
                        {
                            errorEnTemporada = false;
                        }
                    }
                }

                if (errorEnTemporada)
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: La temporada {2} no coincide con el pedido comercial {3}, temporada {4}", i + 1, temporadaIndex, temporada, pedidoComercial.Id, pedidoComercial.TemporadaId));
                }

                bool errorEnDestino = true;
                if (!String.IsNullOrEmpty(destino))
                {
                    int destinoInt;
                    if (int.TryParse(destino, out destinoInt))
                    {
                        if (destinoInt == pedidoComercial.DestinoId)
                        {
                            errorEnDestino = false;
                        }
                    }
                }

                if (errorEnDestino)
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: El destino {2} no coincide con el pedido comercial {3}, destino {4}", i + 1, destinoIndex, destino, pedidoComercial.Id, pedidoComercial.DestinoId));
                }

                if (!String.IsNullOrEmpty(producto) && producto.Length == 8)
                {
                    pedidoComercialDetalle.ProductoIdExterno = producto;
                }
                else
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: El valor {2} no se pudo interpretar. Controle que sea un valor de 8 letras", i, productoIndex, producto));
                }

                if (!String.IsNullOrEmpty(color) && color.Length == 3)
                {
                    pedidoComercialDetalle.ColorId = color;
                }
                else
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: El valor {2} no se pudo interpretar. Controle que sea un valor de 3 letras", i, colorIndex, color));
                }

                if (Int32.TryParse(dataTable.Rows[i][cantidadIndex].ToString(), out cantidad))
                {
                    pedidoComercialDetalle.Cantidad = cantidad;
                }
                else
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: El valor {2} no se pudo interpretar. Controle que sea un número entero", i, cantidadIndex, cantidad));
                }

                pedidoComercialDetalleList.Add(pedidoComercialDetalle);

            }

            return pedidoComercialDetalleList;
        }

        /// <summary>
        /// Recibe el pedido comercial detalle
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static List<PresupuestoProduccionDetalleProd> GetPresupuestoProduccionDetalleProdFromExcel(string filePath, PresupuestoProduccion presupuestoProduccion, Temporada temporadaObj, List<string> parseErrors)
        {
            List<PresupuestoProduccionDetalleProd> presupuestoProduccionDetalleProdList = new List<PresupuestoProduccionDetalleProd>();

            DataTable dataTable = GetDataTableFromExcel(filePath);
            int temporadaIndex = 0;
            int destinoIndex = 0;
            int proveedorIndex = 0;
            int productoIndex = 0;
            int colorIndex = 0;
            int calidadIndex = 0;
            int totalIndex = 0;

            const int cantidadColumnas = 6;

            if (dataTable.Columns.Count <= cantidadColumnas)
            {
                throw new Exception(string.Format("El excel debe contener mas de {0} columnas", cantidadColumnas));
            }

            string value = string.Empty;
            for (int i = 0; i < cantidadColumnas; i++)
            {
                value = dataTable.Columns[i].ColumnName;
                if (value.ToLower() == "temporada")
                {
                    temporadaIndex = i;
                }
                else if (value.ToLower() == "destino")
                {
                    destinoIndex = i;
                }
                else if (value.ToLower() == "proveedor")
                {
                    proveedorIndex = i;
                }
                else if (value.ToLower() == "producto")
                {
                    productoIndex = i;
                }
                else if (value.ToLower() == "color")
                {
                    colorIndex = i;
                }
                else if (value.ToLower() == "calidad")
                {
                    calidadIndex = i;
                }
            }

            HybridDictionary indiceDeSemanas = new HybridDictionary();
            for (int i = dataTable.Columns.Count - 1; i >= 0; i--)
            {
                value = dataTable.Columns[i].ColumnName;
                if (value.ToLower() == "total")
                {
                    totalIndex = i;
                }
                else if (value.ToLower().StartsWith("se"))
                {
                    string numeroStr = value.Split('-')[1];
                    int numeroSemana;
                    if (int.TryParse(numeroStr, out numeroSemana))
                    {
                        indiceDeSemanas.Add(i, numeroSemana);
                    }
                    else
                    {
                        parseErrors.Add(string.Format("No se pudo parsear la el número de semana de la cabecera en la columna {0} valor {1}", i, numeroStr));
                        throw new Exception(string.Format("No se pudo parsear la el número de semana de la cabecera en la columna {0} valor {1}", i, numeroStr));
                    }
                }
            }

            if (temporadaObj.NumeroSemanas != indiceDeSemanas.Count)
            {
                parseErrors.Add(string.Format("La temporada {0}({1}) tiene {2} semanas y en el archivo hay {3} semanas. La cantidad de semanas debe coincidir.", temporadaObj.Nombre, temporadaObj.Id, temporadaObj.NumeroSemanas, indiceDeSemanas.Count));
                throw new Exception(string.Format("La temporada {0}({1}) tiene {2} semanas y en el archivo hay {3} semanas. La cantidad de semanas debe coincidir.", temporadaObj.Nombre, temporadaObj.Id, temporadaObj.NumeroSemanas, indiceDeSemanas.Count));
            }

            // TODO: validar columnas por semana  
            string temporada;
            string destino;
            string proveedor;
            string productoId;
            string colorId;
            int calidadId;

            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                temporada = dataTable.Rows[i][temporadaIndex].ToString();
                bool errorEnTemporada = true;
                if (!String.IsNullOrEmpty(temporada))
                {
                    int temporadaInt;
                    if (int.TryParse(temporada, out temporadaInt))
                    {
                        if (temporadaInt == presupuestoProduccion.TemporadaId)
                        {
                            errorEnTemporada = false;
                        }
                    }
                }

                if (errorEnTemporada)
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: La temporada {2} no coincide con el presupuesto de producción {3}, temporada {4}", i + 1, temporadaIndex, temporada, presupuestoProduccion.Id, presupuestoProduccion.TemporadaId));
                }

                destino = dataTable.Rows[i][destinoIndex].ToString();
                bool errorEnDestino = true;
                if (!String.IsNullOrEmpty(destino))
                {
                    int destinoInt;
                    if (int.TryParse(destino, out destinoInt))
                    {
                        if (destinoInt == presupuestoProduccion.DestinoId)
                        {
                            errorEnDestino = false;
                        }
                    }
                }

                if (errorEnDestino)
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: El destino {2} no coincide con el presupuesto de producción {3}, destino {4}", i + 1, destinoIndex, destino, presupuestoProduccion.Id, presupuestoProduccion.DestinoId));
                }

                proveedor = dataTable.Rows[i][proveedorIndex].ToString();
                bool errorenProveedor = true;
                if (!String.IsNullOrEmpty(proveedor))
                {
                    int proveedorInt;
                    if (Int32.TryParse(proveedor, out proveedorInt))
                    {
                        if (proveedorInt == presupuestoProduccion.ProveedorIdExterno)
                        {
                            errorenProveedor = false;
                        }
                    }
                }

                if (errorenProveedor)
                {
                    parseErrors.Add(string.Format("Fila {0}, columna {1}: El proveedor {2} no coincide con el presupuesto de producción {3}, proveedor {4}", i + 1, proveedorIndex, proveedor, presupuestoProduccion.Id, presupuestoProduccion.ProveedorIdExterno));
                }

                PresupuestoProduccionDetalleProd presupuestoProduccionDetalleProd = new PresupuestoProduccionDetalleProd();
                productoId = dataTable.Rows[i][productoIndex].ToString();
                if (!String.IsNullOrEmpty(productoId))
                {
                    presupuestoProduccionDetalleProd.ProductoIdExterno = productoId;
                }
                else
                {
                    parseErrors.Add(string.Format("Fila: {0}, columna: {1}, el valor del producto '{2}' no se pudo parsear", i, productoIndex, productoId));
                }

                colorId = dataTable.Rows[i][colorIndex].ToString();
                if (!String.IsNullOrEmpty(colorId))
                {
                    presupuestoProduccionDetalleProd.ColorId = colorId;
                }
                else
                {
                    parseErrors.Add(string.Format("Fila: {0}, columna: {1}, el valor del color '{2}' no se pudo parsear", i, colorIndex, colorId));
                }

                if (Int32.TryParse(dataTable.Rows[i][calidadIndex].ToString(), out calidadId))
                {
                    presupuestoProduccionDetalleProd.CalidadId = calidadId;
                }
                else
                {
                    parseErrors.Add(string.Format("Fila: {0}, columna: {1}, el valor de calidad '{2}' no se pudo parsear", i, calidadIndex, calidadId));
                }

                int numeroSemana = 0;
                List<PresupuestoProduccionDetalleProdSemanal> cantidadesPorSemana = new List<PresupuestoProduccionDetalleProdSemanal>();
                for (int j = cantidadColumnas; j < dataTable.Columns.Count; j++)
                {
                    if (indiceDeSemanas.Contains(j))
                    {
                        try
                        {
                            PresupuestoProduccionDetalleProdSemanal cantPorSemana = new PresupuestoProduccionDetalleProdSemanal();
                            numeroSemana = Convert.ToInt32(indiceDeSemanas[j]);
                            cantPorSemana.NumeroSemana = numeroSemana;
                            cantPorSemana.Cantidad = Convert.ToInt32(dataTable.Rows[i][j].ToString());
                            presupuestoProduccionDetalleProd.CantidadesPorSemana.Add(cantPorSemana);
                        }
                        catch (Exception ex)
                        {
                            parseErrors.Add(string.Format("Excepción en fila {1} columna {2}: {0}", ex.Message, i, j));
                            break;
                        }
                    }
                }

                presupuestoProduccionDetalleProdList.Add(presupuestoProduccionDetalleProd);

            }

            return presupuestoProduccionDetalleProdList;
        }

        private static DataTable GetDataTableFromExcel(string filePath)
        {
            //<add name="xls" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Sample1.xls;Extended Properties=Excel 8.0"/>
            //<add name="xlsx" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Sample.xlsx;Extended Properties=Excel 12.0"/>            
            string connectionString = string.Format(@"Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0};Extended Properties=""Excel 12.0;""", filePath);

            OleDbConnection objConnection = new OleDbConnection();

            try
            {
                objConnection = new OleDbConnection(connectionString);

                objConnection.Open();

                DataTable dtSchema = objConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

                string sheetName = dtSchema.Rows[0]["TABLE_NAME"].ToString();

                var adapter = new OleDbDataAdapter("SELECT * FROM [" + sheetName + "]", objConnection);
                var ds = new DataSet();

                adapter.Fill(ds, "anyNameHere");

                return ds.Tables["anyNameHere"];
            }
            finally
            {
                objConnection.Close();
            }
        }

        private static bool CheckIfSheetNameExists(string sheetName, DataTable dtSchema)
        {
            foreach (DataRow dataRow in dtSchema.Rows)
            {
                if (sheetName == dataRow["TABLE_NAME"].ToString())
                {
                    return true;
                }
            }
            return false;
        }

        #region oldExcel
        //    public static List<PedidoComercialDetalle> GetPedidoComercialDetalleFromExcel(string filePath)
        //    {
        //        List<PedidoComercialDetalle> pedidoComercialDetalleList = new List<PedidoComercialDetalle>();

        //        Excel.Application excelApplication = new Excel.Application();
        //        try
        //        {
        //            Excel.Workbook workBook = excelApplication.Workbooks.Open(filePath,
        //                                              0,
        //                                              true,
        //                                              5,
        //                                              "",
        //                                              "",
        //                                              true,
        //                                              Excel.XlPlatform.xlWindows,
        //                                              "\t",
        //                                              false,
        //                                              false,
        //                                              0,
        //                                              true,
        //                                              1,
        //                                              0);

        //            Excel.Worksheet workSheet = (Excel.Worksheet)workBook.ActiveSheet;
        //            int rowIndexInt = 1;
        //            int colIndexInt = 1;
        //            object rowIndex = 1;
        //            object colIndex1 = 1;
        //            bool isTituloRead = false;

        //            int temporadaIndex = 0;
        //            int destinoIndex = 0;
        //            int productoIndex = 0;
        //            int colorIndex = 0;
        //            int cantidadIndex = 0;
        //            int columnasTitulo = 0;

        //            while (((Excel.Range)workSheet.Cells[rowIndex, colIndex1]).Value2 != null)
        //            {
        //                if (!isTituloRead)
        //                {
        //                    while (((Excel.Range)workSheet.Cells[rowIndex, colIndex1]).Value2 != null)
        //                    {
        //                        string value = ((Excel.Range)workSheet.Cells[rowIndex, colIndex1]).Value2.ToString();
        //                        if (value.ToLower() == "temporada")
        //                        {
        //                            temporadaIndex = (int)colIndex1;
        //                            columnasTitulo++;
        //                        }
        //                        else if (value.ToLower() == "destino")
        //                        {
        //                            destinoIndex = (int)colIndex1;
        //                            columnasTitulo++;
        //                        }
        //                        else if (value.ToLower() == "producto")
        //                        {
        //                            productoIndex = (int)colIndex1;
        //                            columnasTitulo++;
        //                        }
        //                        else if (value.ToLower() == "color")
        //                        {
        //                            colorIndex = (int)colIndex1;
        //                            columnasTitulo++;
        //                        }
        //                        else if (value.ToLower() == "cantidad")
        //                        {
        //                            cantidadIndex = (int)colIndex1;
        //                            columnasTitulo++;
        //                        }

        //                        isTituloRead = columnasTitulo == 5;
        //                        colIndexInt++;
        //                        colIndex1 = colIndexInt;
        //                    }
        //                    colIndex1 = productoIndex;
        //                }
        //                else
        //                {
        //                    PedidoComercialDetalle pedidoComercialDetalle = new PedidoComercialDetalle();
        //                    pedidoComercialDetalle.Producto = Convert.ToInt64(((Excel.Range)workSheet.Cells[rowIndex, productoIndex]).Value2);
        //                    pedidoComercialDetalle.Color = Convert.ToInt64(((Excel.Range)workSheet.Cells[rowIndex, colorIndex]).Value2);
        //                    pedidoComercialDetalle.Cantidad = Convert.ToInt32(((Excel.Range)workSheet.Cells[rowIndex, cantidadIndex]).Value2);
        //                    pedidoComercialDetalleList.Add(pedidoComercialDetalle);
        //                }

        //                rowIndexInt++;
        //                rowIndex = rowIndexInt;
        //            }
        //        }
        //        finally
        //        {
        //            excelApplication.Quit();
        //        }

        //        return pedidoComercialDetalleList;
        //    }
        //}
        #endregion
    }
}